bitkeeper revision 1.1159.170.90 (41e53190NTwQxrBNj2UypCRVNj7fyQ)
authorkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 12 Jan 2005 14:17:52 +0000 (14:17 +0000)
committerkaf24@scramble.cl.cam.ac.uk <kaf24@scramble.cl.cam.ac.uk>
Wed, 12 Jan 2005 14:17:52 +0000 (14:17 +0000)
More seg-fixup cleanups and safety fixes.

xen/arch/x86/traps.c
xen/arch/x86/x86_32/seg_fixup.c
xen/include/asm-x86/mm.h

index ed996e30a0f97a6a4caf81a79ca2b3a255160944..2bdb160373a19b14980db7e3935642aef61705b9 100644 (file)
@@ -382,13 +382,27 @@ asmlinkage void do_machine_check(struct xen_regs *regs)
     fatal_trap(TRAP_machine_check, regs);
 }
 
-asmlinkage int do_page_fault(struct xen_regs *regs)
+void propagate_page_fault(unsigned long addr, u16 error_code)
 {
     trap_info_t *ti;
+    struct domain *d = current;
+    struct trap_bounce *tb = &d->thread.trap_bounce;
+
+    ti = d->thread.traps + 14;
+    tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
+    tb->cr2        = addr;
+    tb->error_code = error_code;
+    tb->cs         = ti->cs;
+    tb->eip        = ti->address;
+    if ( TI_GET_IF(ti) )
+        d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
+}
+
+asmlinkage int do_page_fault(struct xen_regs *regs)
+{
     unsigned long off, addr, fixup;
     struct domain *d = current;
     extern int map_ldt_shadow_page(unsigned int);
-    struct trap_bounce *tb = &d->thread.trap_bounce;
     int cpu = d->processor;
 
     __asm__ __volatile__ ("movl %%cr2,%0" : "=r" (addr) : );
@@ -437,14 +451,7 @@ asmlinkage int do_page_fault(struct xen_regs *regs)
     if ( !GUEST_FAULT(regs) )
         goto xen_fault;
 
-    ti = d->thread.traps + 14;
-    tb->flags = TBF_EXCEPTION | TBF_EXCEPTION_ERRCODE | TBF_EXCEPTION_CR2;
-    tb->cr2        = addr;
-    tb->error_code = regs->error_code;
-    tb->cs         = ti->cs;
-    tb->eip        = ti->address;
-    if ( TI_GET_IF(ti) )
-        d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
+    propagate_page_fault(addr, regs->error_code);
     return 0; 
 
  xen_fault:
index 7c53def147f32a6d80638ed010be18800588e01c..9009971d267e21f6b72e70f2b12992999852c14d 100644 (file)
@@ -278,9 +278,7 @@ void *decode_reg(struct xen_regs *regs, u8 b)
 
 /*
  * Called from the general-protection fault handler to attempt to decode
- * and emulate an instruction that depends on 4GB segments. At this point
- * we assume that the instruction itself is paged into memory (the CPU
- * must have triggered this in order to decode the instruction itself).
+ * and emulate an instruction that depends on 4GB segments.
  */
 int gpf_emulate_4gb(struct xen_regs *regs)
 {
@@ -315,7 +313,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
         if ( get_user(b, pb) )
         {
             DPRINTK("Fault while accessing byte %d of instruction\n", pb-eip);
-            goto fail;
+            goto page_fault;
         }
 
         if ( (pb - eip) >= 15 )
@@ -371,10 +369,21 @@ int gpf_emulate_4gb(struct xen_regs *regs)
         switch ( decode & 7 )
         {
         case 1:
-            offset = (long)(*(char *)pb);
+            if ( get_user(b, pb) )
+            {
+                DPRINTK("Fault while extracting <moffs8>.\n");
+                goto page_fault;
+            }
+            pb++;
+            offset = (signed long)(signed char)b;
             goto skip_modrm;
         case 4:
-            offset = *(long *)pb;
+            if ( get_user(offset, (u32 *)pb) )
+            {
+                DPRINTK("Fault while extracting <disp8>.\n");
+                goto page_fault;
+            }
+            pb += 4;
             goto skip_modrm;
         default:
             goto fail;
@@ -388,7 +397,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
     if ( get_user(modrm, pb) )
     {
         DPRINTK("Fault while extracting modrm byte\n");
-        goto fail;
+        goto page_fault;
     }
 
     pb++;
@@ -420,7 +429,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
             if ( get_user(disp32, (u32 *)pb) )
             {
                 DPRINTK("Fault while extracting <disp8>.\n");
-                goto fail;
+                goto page_fault;
             }
             pb += 4;
         }
@@ -432,7 +441,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
         if ( get_user(disp8, pb) )
         {
             DPRINTK("Fault while extracting <disp8>.\n");
-            goto fail;
+            goto page_fault;
         }
         pb++;
         disp32 = (disp8 & 0x80) ? (disp8 | ~0xff) : disp8;;
@@ -444,7 +453,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
         if ( get_user(disp32, (u32 *)pb) )
         {
             DPRINTK("Fault while extracting <disp8>.\n");
-            goto fail;
+            goto page_fault;
         }
         pb += 4;
         break;
@@ -478,7 +487,7 @@ int gpf_emulate_4gb(struct xen_regs *regs)
             d->shared_info->vcpu_data[0].evtchn_upcall_mask = 1;
     }
 
-    return 1;
+    return EXCRET_fault_fixed;
 
  fixme:
     DPRINTK("Undecodable instruction %02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x "
@@ -488,4 +497,8 @@ int gpf_emulate_4gb(struct xen_regs *regs)
             regs->cs, regs->eip);
  fail:
     return 0;
+
+ page_fault:
+    propagate_page_fault((unsigned long)pb, 4);
+    return EXCRET_fault_fixed;
 }
index 529ecbfc5c657437e93b4e65580a7761026d7355..8f35bd96e78c9440c51dc5d6d0b87d4c1847e6c0 100644 (file)
@@ -296,4 +296,6 @@ void audit_domains(void);
 #define audit_domains()  ((void)0)
 #endif
 
+void propagate_page_fault(unsigned long addr, u16 error_code);
+
 #endif /* __ASM_X86_MM_H__ */